home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / lib / firefox-3.5.5 / components / nsBrowserGlue.js < prev    next >
Text File  |  2009-11-09  |  43KB  |  1,081 lines

  1. //@line 42 "/build/buildd/firefox-3.5-3.5.5+nobinonly/build-tree/mozilla/browser/components/nsBrowserGlue.js"
  2.  
  3. const Ci = Components.interfaces;
  4. const Cc = Components.classes;
  5. const Cr = Components.results;
  6. const Cu = Components.utils;
  7.  
  8. const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  9.  
  10. Cu.import("resource://gre/modules/XPCOMUtils.jsm");
  11. Cu.import("resource:///modules/distribution.js");
  12.  
  13. const PREF_EM_NEW_ADDONS_LIST = "extensions.newAddons";
  14.  
  15. // Check to see if bookmarks need backing up once per
  16. // day on 1 hour idle.
  17. const BOOKMARKS_ARCHIVE_IDLE_TIME = 60 * 60;
  18.  
  19. // Backup bookmarks once every 24 hours.
  20. const BOOKMARKS_ARCHIVE_INTERVAL = 86400 * 1000;
  21.  
  22. // Factory object
  23. const BrowserGlueServiceFactory = {
  24.   _instance: null,
  25.   createInstance: function (outer, iid) 
  26.   {
  27.     if (outer != null)
  28.       throw Components.results.NS_ERROR_NO_AGGREGATION;
  29.     return this._instance == null ?
  30.       this._instance = new BrowserGlue() : this._instance;
  31.   }
  32. };
  33.  
  34. // Constructor
  35.  
  36. function BrowserGlue() {
  37.  
  38.   this.__defineGetter__("_prefs", function() {
  39.     delete this._prefs;
  40.     return this._prefs = Cc["@mozilla.org/preferences-service;1"].
  41.                          getService(Ci.nsIPrefBranch);
  42.   });
  43.  
  44.   this.__defineGetter__("_bundleService", function() {
  45.     delete this._bundleService;
  46.     return this._bundleService = Cc["@mozilla.org/intl/stringbundle;1"].
  47.                                  getService(Ci.nsIStringBundleService);
  48.   });
  49.  
  50.   this.__defineGetter__("_idleService", function() {
  51.     delete this._idleService;
  52.     return this._idleService = Cc["@mozilla.org/widget/idleservice;1"].
  53.                            getService(Ci.nsIIdleService);
  54.   });
  55.  
  56.   this.__defineGetter__("_observerService", function() {
  57.     delete this._observerService;
  58.     return this._observerService = Cc['@mozilla.org/observer-service;1'].
  59.                                    getService(Ci.nsIObserverService);
  60.   });
  61.  
  62.   this._init();
  63. }
  64.  
  65. BrowserGlue.prototype = {
  66.   
  67.   _saveSession: false,
  68.  
  69.   _setPrefToSaveSession: function()
  70.   {
  71.     this._prefs.setBoolPref("browser.sessionstore.resume_session_once", true);
  72.  
  73.     // This method can be called via [NSApplication terminate:] on Mac, which
  74.     // ends up causing prefs not to be flushed to disk, so we need to do that
  75.     // explicitly here. See bug 497652.
  76.     this._prefs.QueryInterface(Ci.nsIPrefService).savePrefFile(null);
  77.   },
  78.  
  79.   // nsIObserver implementation 
  80.   observe: function(subject, topic, data) 
  81.   {
  82.     switch(topic) {
  83.       case "xpcom-shutdown":
  84.         this._dispose();
  85.         break;
  86.       case "prefservice:after-app-defaults":
  87.         this._onAppDefaults();
  88.         break;
  89.       case "final-ui-startup":
  90.         this._onProfileStartup();
  91.         break;
  92.       case "sessionstore-windows-restored":
  93.         this._onBrowserStartup();
  94.         break;
  95.       case "browser:purge-session-history":
  96.         // reset the console service's error buffer
  97.         const cs = Cc["@mozilla.org/consoleservice;1"].
  98.                    getService(Ci.nsIConsoleService);
  99.         cs.logStringMessage(null); // clear the console (in case it's open)
  100.         cs.reset();
  101.         break;
  102.       case "quit-application-requested":
  103.         this._onQuitRequest(subject, data);
  104.         break;
  105.       case "quit-application-granted":
  106.         if (this._saveSession) {
  107.           this._setPrefToSaveSession();
  108.         }
  109.         // Everything that uses Places during shutdown should be here, since
  110.         // on quit-application Places database connection will be closed
  111.         // and history synchronization could fail.
  112.         this._onProfileShutdown();
  113.         break;
  114.       case "session-save":
  115.         this._setPrefToSaveSession();
  116.         subject.QueryInterface(Ci.nsISupportsPRBool);
  117.         subject.data = true;
  118.         break;
  119.       case "places-init-complete":
  120.         this._initPlaces();
  121.         this._observerService.removeObserver(this, "places-init-complete");
  122.         // no longer needed, since history was initialized completely.
  123.         this._observerService.removeObserver(this, "places-database-locked");
  124.         break;
  125.       case "places-database-locked":
  126.         this._isPlacesDatabaseLocked = true;
  127.         // stop observing, so further attempts to load history service
  128.         // do not show the prompt.
  129.         this._observerService.removeObserver(this, "places-database-locked");
  130.         break;
  131.       case "idle":
  132.         if (this._idleService.idleTime > BOOKMARKS_ARCHIVE_IDLE_TIME * 1000) {
  133.           // Back up bookmarks.
  134.           this._archiveBookmarks();
  135.         }
  136.         break;
  137.     }
  138.   }, 
  139.  
  140.   // initialization (called on application startup) 
  141.   _init: function() 
  142.   {
  143.     // observer registration
  144.     const osvr = this._observerService;
  145.     osvr.addObserver(this, "xpcom-shutdown", false);
  146.     osvr.addObserver(this, "prefservice:after-app-defaults", false);
  147.     osvr.addObserver(this, "final-ui-startup", false);
  148.     osvr.addObserver(this, "sessionstore-windows-restored", false);
  149.     osvr.addObserver(this, "browser:purge-session-history", false);
  150.     osvr.addObserver(this, "quit-application-requested", false);
  151.     osvr.addObserver(this, "quit-application-granted", false);
  152.     osvr.addObserver(this, "session-save", false);
  153.     osvr.addObserver(this, "places-init-complete", false);
  154.     osvr.addObserver(this, "places-database-locked", false);
  155.   },
  156.  
  157.   // cleanup (called on application shutdown)
  158.   _dispose: function() 
  159.   {
  160.     // observer removal 
  161.     const osvr = this._observerService;
  162.     osvr.removeObserver(this, "xpcom-shutdown");
  163.     osvr.removeObserver(this, "prefservice:after-app-defaults");
  164.     osvr.removeObserver(this, "final-ui-startup");
  165.     osvr.removeObserver(this, "sessionstore-windows-restored");
  166.     osvr.removeObserver(this, "browser:purge-session-history");
  167.     osvr.removeObserver(this, "quit-application-requested");
  168.     osvr.removeObserver(this, "quit-application-granted");
  169.     osvr.removeObserver(this, "session-save");
  170.   },
  171.  
  172.   _onAppDefaults: function()
  173.   {
  174.     // apply distribution customizations (prefs)
  175.     // other customizations are applied in _onProfileStartup()
  176.     var distro = new DistributionCustomizer();
  177.     distro.applyPrefDefaults();
  178.   },
  179.  
  180.   // profile startup handler (contains profile initialization routines)
  181.   _onProfileStartup: function() 
  182.   {
  183.     this.Sanitizer.onStartup();
  184.     // check if we're in safe mode
  185.     var app = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).
  186.               QueryInterface(Ci.nsIXULRuntime);
  187.     if (app.inSafeMode) {
  188.       var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
  189.                getService(Ci.nsIWindowWatcher);
  190.       ww.openWindow(null, "chrome://browser/content/safeMode.xul", 
  191.                     "_blank", "chrome,centerscreen,modal,resizable=no", null);
  192.     }
  193.  
  194.     // apply distribution customizations
  195.     // prefs are applied in _onAppDefaults()
  196.     var distro = new DistributionCustomizer();
  197.     distro.applyCustomizations();
  198.  
  199.     // handle any UI migration
  200.     this._migrateUI();
  201.  
  202.     this._observerService.notifyObservers(null, "browser-ui-startup-complete", "");
  203.   },
  204.  
  205.   // profile shutdown handler (contains profile cleanup routines)
  206.   _onProfileShutdown: function() 
  207.   {
  208.     this._shutdownPlaces();
  209.     this._idleService.removeIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
  210.     this.Sanitizer.onShutdown();
  211.   },
  212.  
  213.   // Browser startup complete. All initial windows have opened.
  214.   _onBrowserStartup: function()
  215.   {
  216.     // Show about:rights notification, if needed.
  217.     if (this._shouldShowRights())
  218.       this._showRightsNotification();
  219.  
  220.     // If new add-ons were installed during startup open the add-ons manager.
  221.     if (this._prefs.prefHasUserValue(PREF_EM_NEW_ADDONS_LIST)) {
  222.       var args = Cc["@mozilla.org/supports-array;1"].
  223.                  createInstance(Ci.nsISupportsArray);
  224.       var str = Cc["@mozilla.org/supports-string;1"].
  225.                 createInstance(Ci.nsISupportsString);
  226.       str.data = "";
  227.       args.AppendElement(str);
  228.       var str = Cc["@mozilla.org/supports-string;1"].
  229.                 createInstance(Ci.nsISupportsString);
  230.       str.data = this._prefs.getCharPref(PREF_EM_NEW_ADDONS_LIST);
  231.       args.AppendElement(str);
  232.       const EMURL = "chrome://mozapps/content/extensions/extensions.xul";
  233.       const EMFEATURES = "chrome,menubar,extra-chrome,toolbar,dialog=no,resizable";
  234.       var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
  235.                getService(Ci.nsIWindowWatcher);
  236.       ww.openWindow(null, EMURL, "_blank", EMFEATURES, args);
  237.       this._prefs.clearUserPref(PREF_EM_NEW_ADDONS_LIST);
  238.     }
  239.  
  240.     // Load the "more info" page for a locked places.sqlite
  241.     // This property is set earlier in the startup process:
  242.     // nsPlacesDBFlush loads after profile-after-change and initializes
  243.     // the history service, which sends out places-database-locked
  244.     // which sets this property.
  245.     if (this._isPlacesDatabaseLocked) {
  246.       this._showPlacesLockedNotificationBox();
  247.     }
  248.   },
  249.  
  250.   _onQuitRequest: function(aCancelQuit, aQuitType)
  251.   {
  252.     // If user has already dismissed quit request, then do nothing
  253.     if ((aCancelQuit instanceof Ci.nsISupportsPRBool) && aCancelQuit.data)
  254.       return;
  255.  
  256.     var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
  257.              getService(Ci.nsIWindowMediator);
  258.  
  259.     var windowcount = 0;
  260.     var pagecount = 0;
  261.     var browserEnum = wm.getEnumerator("navigator:browser");
  262.     while (browserEnum.hasMoreElements()) {
  263.       windowcount++;
  264.  
  265.       var browser = browserEnum.getNext();
  266.       var tabbrowser = browser.document.getElementById("content");
  267.       if (tabbrowser)
  268.         pagecount += tabbrowser.browsers.length;
  269.     }
  270.  
  271.     this._saveSession = false;
  272.     if (pagecount < 2)
  273.       return;
  274.  
  275.     if (aQuitType != "restart")
  276.       aQuitType = "quit";
  277.  
  278.     var showPrompt = true;
  279.     try {
  280.       // browser.warnOnQuit is a hidden global boolean to override all quit prompts
  281.       // browser.warnOnRestart specifically covers app-initiated restarts where we restart the app
  282.       // browser.tabs.warnOnClose is the global "warn when closing multiple tabs" pref
  283.  
  284.       var sessionWillBeSaved = this._prefs.getIntPref("browser.startup.page") == 3 ||
  285.                                this._prefs.getBoolPref("browser.sessionstore.resume_session_once");
  286.       if (sessionWillBeSaved || !this._prefs.getBoolPref("browser.warnOnQuit"))
  287.         showPrompt = false;
  288.       else if (aQuitType == "restart")
  289.         showPrompt = this._prefs.getBoolPref("browser.warnOnRestart");
  290.       else
  291.         showPrompt = this._prefs.getBoolPref("browser.tabs.warnOnClose");
  292.     } catch (ex) {}
  293.  
  294.     // Never show a prompt inside the private browsing mode
  295.     var inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
  296.                             getService(Ci.nsIPrivateBrowsingService).
  297.                             privateBrowsingEnabled;
  298.     if (!showPrompt || inPrivateBrowsing)
  299.       return false;
  300.  
  301.     var buttonChoice = 0;
  302.     var quitBundle = this._bundleService.createBundle("chrome://browser/locale/quitDialog.properties");
  303.     var brandBundle = this._bundleService.createBundle("chrome://branding/locale/brand.properties");
  304.  
  305.     var appName = brandBundle.GetStringFromName("brandShortName");
  306.     var quitDialogTitle = quitBundle.formatStringFromName(aQuitType + "DialogTitle",
  307.                                                           [appName], 1);
  308.  
  309.     var message;
  310.     if (aQuitType == "restart")
  311.       message = quitBundle.formatStringFromName("messageRestart",
  312.                                                 [appName], 1);
  313.     else if (windowcount == 1)
  314.       message = quitBundle.formatStringFromName("messageNoWindows",
  315.                                                 [appName], 1);
  316.     else
  317.       message = quitBundle.formatStringFromName("message",
  318.                                                 [appName], 1);
  319.  
  320.     var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
  321.                         getService(Ci.nsIPromptService);
  322.  
  323.     var flags = promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0 +
  324.                 promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_1 +
  325.                 promptService.BUTTON_POS_0_DEFAULT;
  326.  
  327.     var neverAsk = {value:false};
  328.     var button0Title, button2Title;
  329.     var button1Title = quitBundle.GetStringFromName("cancelTitle");
  330.     var neverAskText = quitBundle.GetStringFromName("neverAsk");
  331.  
  332.     if (aQuitType == "restart")
  333.       button0Title = quitBundle.GetStringFromName("restartTitle");
  334.     else {
  335.       flags += promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_2;
  336.       button0Title = quitBundle.GetStringFromName("saveTitle");
  337.       button2Title = quitBundle.GetStringFromName("quitTitle");
  338.     }
  339.  
  340.     buttonChoice = promptService.confirmEx(null, quitDialogTitle, message,
  341.                                  flags, button0Title, button1Title, button2Title,
  342.                                  neverAskText, neverAsk);
  343.  
  344.     switch (buttonChoice) {
  345.     case 2: // Quit
  346.       if (neverAsk.value)
  347.         this._prefs.setBoolPref("browser.tabs.warnOnClose", false);
  348.       break;
  349.     case 1: // Cancel
  350.       aCancelQuit.QueryInterface(Ci.nsISupportsPRBool);
  351.       aCancelQuit.data = true;
  352.       break;
  353.     case 0: // Save & Quit
  354.       this._saveSession = true;
  355.       if (neverAsk.value) {
  356.         if (aQuitType == "restart")
  357.           this._prefs.setBoolPref("browser.warnOnRestart", false);
  358.         else {
  359.           // always save state when shutting down
  360.           this._prefs.setIntPref("browser.startup.page", 3);
  361.         }
  362.       }
  363.       break;
  364.     }
  365.   },
  366.  
  367.   /*
  368.    * _shouldShowRights - Determines if the user should be shown the
  369.    * about:rights notification. The notification should *not* be shown if
  370.    * we've already shown the current version, or if the override pref says to
  371.    * never show it. The notification *should* be shown if it's never been seen
  372.    * before, if a newer version is available, or if the override pref says to
  373.    * always show it.
  374.    */
  375.   _shouldShowRights : function () {
  376.     // Look for an unconditional override pref. If set, do what it says.
  377.     // (true --> never show, false --> always show)
  378.     try {
  379.       return !this._prefs.getBoolPref("browser.rights.override");
  380.     } catch (e) { }
  381.     // Ditto, for the legacy EULA pref.
  382.     try {
  383.       return !this._prefs.getBoolPref("browser.EULA.override");
  384.     } catch (e) { }
  385.  
  386. //@line 430 "/build/buildd/firefox-3.5-3.5.5+nobinonly/build-tree/mozilla/browser/components/nsBrowserGlue.js"
  387.  
  388.     // Look to see if the user has seen the current version or not.
  389.     var currentVersion = this._prefs.getIntPref("browser.rights.version");
  390.     try {
  391.       return !this._prefs.getBoolPref("browser.rights." + currentVersion + ".shown");
  392.     } catch (e) { }
  393.  
  394.     // Legacy: If the user accepted a EULA, we won't annoy them with the
  395.     // equivalent about:rights page until the version changes.
  396.     try {
  397.       return !this._prefs.getBoolPref("browser.EULA." + currentVersion + ".accepted");
  398.     } catch (e) { }
  399.  
  400.     // We haven't shown the notification before, so do so now.
  401.     return true;
  402.   },
  403.  
  404.   _showRightsNotification : function () {
  405.     // Stick the notification onto the selected tab of the active browser window.
  406.     var win = this.getMostRecentBrowserWindow();
  407.     var browser = win.gBrowser; // for closure in notification bar callback
  408.     var notifyBox = browser.getNotificationBox();
  409.  
  410.     var brandBundle  = this._bundleService.createBundle("chrome://branding/locale/brand.properties");
  411.     var rightsBundle = this._bundleService.createBundle("chrome://browser/locale/aboutRights.properties");
  412.  
  413.     var buttonLabel      = rightsBundle.GetStringFromName("buttonLabel");
  414.     var buttonAccessKey  = rightsBundle.GetStringFromName("buttonAccessKey");
  415.     var productName      = brandBundle.GetStringFromName("brandFullName");
  416.     var notifyRightsText = rightsBundle.formatStringFromName("notifyRightsText", [productName], 1);
  417.     
  418.     var buttons = [
  419.                     {
  420.                       label:     buttonLabel,
  421.                       accessKey: buttonAccessKey,
  422.                       popup:     null,
  423.                       callback: function(aNotificationBar, aButton) {
  424.                         browser.selectedTab = browser.addTab("about:rights");
  425.                       }
  426.                     }
  427.                   ];
  428.  
  429.     // Set pref to indicate we've shown the notification.
  430.     var currentVersion = this._prefs.getIntPref("browser.rights.version");
  431.     this._prefs.setBoolPref("browser.rights." + currentVersion + ".shown", true);
  432.  
  433.     var box = notifyBox.appendNotification(notifyRightsText, "about-rights", null, notifyBox.PRIORITY_INFO_LOW, buttons);
  434.     box.persistence = 3; // arbitrary number, just so bar sticks around for a bit
  435.   },
  436.  
  437.   // returns the (cached) Sanitizer constructor
  438.   get Sanitizer() 
  439.   {
  440.     if(typeof(Sanitizer) != "function") { // we should dynamically load the script
  441.       Cc["@mozilla.org/moz/jssubscript-loader;1"].
  442.       getService(Ci.mozIJSSubScriptLoader).
  443.       loadSubScript("chrome://browser/content/sanitize.js", null);
  444.     }
  445.     return Sanitizer;
  446.   },
  447.  
  448.   /**
  449.    * Initialize Places
  450.    * - imports the bookmarks html file if bookmarks database is empty, try to
  451.    *   restore bookmarks from a JSON backup if the backend indicates that the
  452.    *   database was corrupt.
  453.    *
  454.    * These prefs can be set up by the frontend:
  455.    *
  456.    * WARNING: setting these preferences to true will overwite existing bookmarks
  457.    *
  458.    * - browser.places.importBookmarksHTML
  459.    *   Set to true will import the bookmarks.html file from the profile folder.
  460.    * - browser.places.smartBookmarksVersion
  461.    *   Set during HTML import to indicate that Smart Bookmarks were created.
  462.    *   Set to -1 to disable Smart Bookmarks creation.
  463.    *   Set to 0 to restore current Smart Bookmarks.
  464.    * - browser.bookmarks.restore_default_bookmarks
  465.    *   Set to true by safe-mode dialog to indicate we must restore default
  466.    *   bookmarks.
  467.    */
  468.   _initPlaces: function bg__initPlaces() {
  469.     // We must instantiate the history service since it will tell us if we
  470.     // need to import or restore bookmarks due to first-run, corruption or
  471.     // forced migration (due to a major schema change).
  472.     var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
  473.                   getService(Ci.nsINavHistoryService);
  474.  
  475.     // If the database is corrupt or has been newly created we should
  476.     // import bookmarks.
  477.     var databaseStatus = histsvc.databaseStatus;
  478.     var importBookmarks = databaseStatus == histsvc.DATABASE_STATUS_CREATE ||
  479.                           databaseStatus == histsvc.DATABASE_STATUS_CORRUPT;
  480.  
  481.     if (databaseStatus == histsvc.DATABASE_STATUS_CREATE) {
  482.       // If the database has just been created, but we already have any
  483.       // bookmark, this is not the initial import.  This can happen after a
  484.       // migration from a different browser since migrators run before us.
  485.       // In such a case we should not import, unless some pref has been set.
  486.       var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
  487.                   getService(Ci.nsINavBookmarksService);
  488.       if (bmsvc.getIdForItemAt(bmsvc.bookmarksMenuFolder, 0) != -1 ||
  489.           bmsvc.getIdForItemAt(bmsvc.toolbarFolder, 0) != -1)
  490.         importBookmarks = false;
  491.     }
  492.  
  493.     // Check if user or an extension has required to import bookmarks.html
  494.     var importBookmarksHTML = false;
  495.     try {
  496.       importBookmarksHTML =
  497.         this._prefs.getBoolPref("browser.places.importBookmarksHTML");
  498.       if (importBookmarksHTML)
  499.         importBookmarks = true;
  500.     } catch(ex) {}
  501.  
  502.     // Check if Safe Mode or the user has required to restore bookmarks from
  503.     // default profile's bookmarks.html
  504.     var restoreDefaultBookmarks = false;
  505.     try {
  506.       restoreDefaultBookmarks =
  507.         this._prefs.getBoolPref("browser.bookmarks.restore_default_bookmarks");
  508.       if (restoreDefaultBookmarks) {
  509.         // Ensure that we already have a bookmarks backup for today
  510.         this._archiveBookmarks();
  511.         importBookmarks = true;
  512.       }
  513.     } catch(ex) {}
  514.  
  515.     // If the user did not require to restore default bookmarks, or import
  516.     // from bookmarks.html, we will try to restore from JSON
  517.     if (importBookmarks && !restoreDefaultBookmarks && !importBookmarksHTML) {
  518.       // get latest JSON backup
  519.       Cu.import("resource://gre/modules/utils.js");
  520.       var bookmarksBackupFile = PlacesUtils.getMostRecentBackup();
  521.       if (bookmarksBackupFile && bookmarksBackupFile.leafName.match("\.json$")) {
  522.         // restore from JSON backup
  523.         PlacesUtils.restoreBookmarksFromJSONFile(bookmarksBackupFile);
  524.         importBookmarks = false;
  525.       }
  526.       else {
  527.         // We have created a new database but we don't have any backup available
  528.         importBookmarks = true;
  529.         var dirService = Cc["@mozilla.org/file/directory_service;1"].
  530.                          getService(Ci.nsIProperties);
  531.         var bookmarksHTMLFile = dirService.get("BMarks", Ci.nsILocalFile);
  532.         if (bookmarksHTMLFile.exists()) {
  533.           // If bookmarks.html is available in current profile import it...
  534.           importBookmarksHTML = true;
  535.         }
  536.         else {
  537.           // ...otherwise we will restore defaults
  538.           restoreDefaultBookmarks = true;
  539.         }
  540.       }
  541.     }
  542.  
  543.     if (!importBookmarks) {
  544.       // Call it here for Fx3 profiles created before the Places folder
  545.       // has been added, otherwise it's called during import.
  546.       this.ensurePlacesDefaultQueriesInitialized();
  547.     }
  548.     else {
  549.       // ensurePlacesDefaultQueriesInitialized() is called by import.
  550.       // Don't try to recreate smart bookmarks if autoExportHTML is true or
  551.       // smart bookmarks are disabled.
  552.       var autoExportHTML = false;
  553.       try {
  554.         autoExportHTML = this._prefs.getBoolPref("browser.bookmarks.autoExportHTML");
  555.       } catch(ex) {}
  556.       var smartBookmarksVersion = 0;
  557.       try {
  558.         smartBookmarksVersion = this._prefs.getIntPref("browser.places.smartBookmarksVersion");
  559.       } catch(ex) {}
  560.       if (!autoExportHTML && smartBookmarksVersion != -1)
  561.         this._prefs.setIntPref("browser.places.smartBookmarksVersion", 0);
  562.  
  563.       // Get bookmarks.html file location
  564.       var dirService = Cc["@mozilla.org/file/directory_service;1"].
  565.                        getService(Ci.nsIProperties);
  566.  
  567.       var bookmarksFile = null;
  568.       if (restoreDefaultBookmarks) {
  569.         // User wants to restore bookmarks.html file from default profile folder
  570.         bookmarksFile = dirService.get("profDef", Ci.nsILocalFile);
  571.         bookmarksFile.append("bookmarks.html");
  572.       }
  573.       else
  574.         bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
  575.  
  576.       if (bookmarksFile.exists()) {
  577.         // import the file
  578.         try {
  579.           var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
  580.                          getService(Ci.nsIPlacesImportExportService);
  581.           importer.importHTMLFromFile(bookmarksFile, true /* overwrite existing */);
  582.         } catch (err) {
  583.           // Report the error, but ignore it.
  584.           Cu.reportError("Bookmarks.html file could be corrupt. " + err);
  585.         }
  586.       }
  587.       else
  588.         Cu.reportError("Unable to find bookmarks.html file.");
  589.  
  590.       // Reset preferences, so we won't try to import again at next run
  591.       if (importBookmarksHTML)
  592.         this._prefs.setBoolPref("browser.places.importBookmarksHTML", false);
  593.       if (restoreDefaultBookmarks)
  594.         this._prefs.setBoolPref("browser.bookmarks.restore_default_bookmarks",
  595.                                 false);
  596.     }
  597.  
  598.     // Initialize bookmark archiving on idle.
  599.     // Once a day, either on idle or shutdown, bookmarks are backed up.
  600.     this._idleService.addIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
  601.   },
  602.  
  603.   /**
  604.    * Places shut-down tasks
  605.    * - back up and archive bookmarks
  606.    * - export bookmarks as HTML, if so configured
  607.    *
  608.    * Note: quit-application-granted notification is received twice
  609.    *       so replace this method with a no-op when first called.
  610.    */
  611.   _shutdownPlaces: function bg__shutdownPlaces() {
  612.     // Backup and archive Places bookmarks.
  613.     this._archiveBookmarks();
  614.  
  615.     // Backup bookmarks to bookmarks.html to support apps that depend
  616.     // on the legacy format.
  617.     var autoExportHTML = false;
  618.     try {
  619.       autoExportHTML = this._prefs.getBoolPref("browser.bookmarks.autoExportHTML");
  620.     } catch(ex) {
  621.       Components.utils.reportError(ex);
  622.     }
  623.  
  624.     if (autoExportHTML) {
  625.       Cc["@mozilla.org/browser/places/import-export-service;1"].
  626.         getService(Ci.nsIPlacesImportExportService).
  627.         backupBookmarksFile();
  628.     }
  629.   },
  630.  
  631.   /**
  632.    * Back up and archive bookmarks
  633.    */
  634.   _archiveBookmarks: function nsBrowserGlue__archiveBookmarks() {
  635.     Cu.import("resource://gre/modules/utils.js");
  636.  
  637.     var lastBackup = PlacesUtils.getMostRecentBackup();
  638.  
  639.     // Backup bookmarks if there aren't any backups or 
  640.     // they haven't been backed up in the last 24 hrs.
  641.     if (!lastBackup ||
  642.         Date.now() - lastBackup.lastModifiedTime > BOOKMARKS_ARCHIVE_INTERVAL) {
  643.       var maxBackups = 5;
  644.       try {
  645.         maxBackups = this._prefs.getIntPref("browser.bookmarks.max_backups");
  646.       } catch(ex) {}
  647.  
  648.       PlacesUtils.archiveBookmarksFile(maxBackups, false /* don't force */);
  649.     }
  650.   },
  651.  
  652.   /**
  653.    * Show the notificationBox for a locked places database.
  654.    */
  655.   _showPlacesLockedNotificationBox: function nsBrowserGlue__showPlacesLockedNotificationBox() {
  656.     var brandBundle  = this._bundleService.createBundle("chrome://branding/locale/brand.properties");
  657.     var applicationName = brandBundle.GetStringFromName("brandShortName");
  658.     var placesBundle = this._bundleService.createBundle("chrome://browser/locale/places/places.properties");
  659.     var title = placesBundle.GetStringFromName("lockPrompt.title");
  660.     var text = placesBundle.formatStringFromName("lockPrompt.text", [applicationName], 1);
  661.     var buttonText = placesBundle.GetStringFromName("lockPromptInfoButton.label");
  662.     var accessKey = placesBundle.GetStringFromName("lockPromptInfoButton.accessKey");
  663.  
  664.     var helpTopic = "places-locked";
  665.     var url = Cc["@mozilla.org/toolkit/URLFormatterService;1"].
  666.               getService(Components.interfaces.nsIURLFormatter).
  667.               formatURLPref("app.support.baseURL");
  668.     url += helpTopic;
  669.  
  670.     var browser = this.getMostRecentBrowserWindow().gBrowser;
  671.  
  672.     var buttons = [
  673.                     {
  674.                       label:     buttonText,
  675.                       accessKey: accessKey,
  676.                       popup:     null,
  677.                       callback:  function(aNotificationBar, aButton) {
  678.                         browser.selectedTab = browser.addTab(url);
  679.                       }
  680.                     }
  681.                   ];
  682.  
  683.     var notifyBox = browser.getNotificationBox();
  684.     var box = notifyBox.appendNotification(text, title, null,
  685.                                            notifyBox.PRIORITY_CRITICAL_MEDIUM,
  686.                                            buttons);
  687.     box.persistence = -1; // Until user closes it
  688.   },
  689.  
  690.   _migrateUI: function bg__migrateUI() {
  691.     var migration = 0;
  692.     try {
  693.       migration = this._prefs.getIntPref("browser.migration.version");
  694.     } catch(ex) {}
  695.  
  696.     if (migration == 0) {
  697.       // this code should always migrate pre-FF3 profiles to the current UI state
  698.  
  699.       // grab the localstore.rdf and make changes needed for new UI
  700.       this._rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
  701.       this._dataSource = this._rdf.GetDataSource("rdf:local-store");
  702.       this._dirty = false;
  703.  
  704.       let currentsetResource = this._rdf.GetResource("currentset");
  705.       let toolbars = ["nav-bar", "toolbar-menubar", "PersonalToolbar"];
  706.       for (let i = 0; i < toolbars.length; i++) {
  707.         let toolbar = this._rdf.GetResource("chrome://browser/content/browser.xul#" + toolbars[i]);
  708.         let currentset = this._getPersist(toolbar, currentsetResource);
  709.         if (!currentset) {
  710.           // toolbar isn't customized
  711.           if (i == 0)
  712.             // new button is in the defaultset, nothing to migrate
  713.             break;
  714.           continue;
  715.         }
  716.         if (/(?:^|,)unified-back-forward-button(?:$|,)/.test(currentset))
  717.           // new button is already there, nothing to migrate
  718.           break;
  719.         if (/(?:^|,)back-button(?:$|,)/.test(currentset)) {
  720.           let newset = currentset.replace(/(^|,)back-button($|,)/,
  721.                                           "$1unified-back-forward-button,back-button$2")
  722.           this._setPersist(toolbar, currentsetResource, newset);
  723.           // done migrating
  724.           break;
  725.         }
  726.       }
  727.  
  728.       // force the RDF to be saved
  729.       if (this._dirty)
  730.         this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();
  731.  
  732.       // free up the RDF service
  733.       this._rdf = null;
  734.       this._dataSource = null;
  735.  
  736.       // update the migration version
  737.       this._prefs.setIntPref("browser.migration.version", 1);
  738.     }
  739.   },
  740.  
  741.   _getPersist: function bg__getPersist(aSource, aProperty) {
  742.     var target = this._dataSource.GetTarget(aSource, aProperty, true);
  743.     if (target instanceof Ci.nsIRDFLiteral)
  744.       return target.Value;
  745.     return null;
  746.   },
  747.  
  748.   _setPersist: function bg__setPersist(aSource, aProperty, aTarget) {
  749.     this._dirty = true;
  750.     try {
  751.       var oldTarget = this._dataSource.GetTarget(aSource, aProperty, true);
  752.       if (oldTarget) {
  753.         if (aTarget)
  754.           this._dataSource.Change(aSource, aProperty, oldTarget, this._rdf.GetLiteral(aTarget));
  755.         else
  756.           this._dataSource.Unassert(aSource, aProperty, oldTarget);
  757.       }
  758.       else {
  759.         this._dataSource.Assert(aSource, aProperty, this._rdf.GetLiteral(aTarget), true);
  760.       }
  761.     }
  762.     catch(ex) {}
  763.   },
  764.  
  765.   // ------------------------------
  766.   // public nsIBrowserGlue members
  767.   // ------------------------------
  768.   
  769.   sanitize: function(aParentWindow) 
  770.   {
  771.     this.Sanitizer.sanitize(aParentWindow);
  772.   },
  773.  
  774.   ensurePlacesDefaultQueriesInitialized: function() {
  775.     const SMART_BOOKMARKS_VERSION = 1;
  776.     const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
  777.     const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion";
  778.  
  779.     // XXX should this be a pref?  see bug #399268
  780.     const MAX_RESULTS = 10;
  781.  
  782.     // get current smart bookmarks version
  783.     // By default, if the pref is not set up, we must create Smart Bookmarks
  784.     var smartBookmarksCurrentVersion = 0;
  785.     try {
  786.       smartBookmarksCurrentVersion = this._prefs.getIntPref(SMART_BOOKMARKS_PREF);
  787.     } catch(ex) {}
  788.  
  789.     // bail out if we don't have to create or update Smart Bookmarks
  790.     if (smartBookmarksCurrentVersion == -1 ||
  791.         smartBookmarksCurrentVersion >= SMART_BOOKMARKS_VERSION)
  792.       return;
  793.  
  794.     var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
  795.                 getService(Ci.nsINavBookmarksService);
  796.     var annosvc = Cc["@mozilla.org/browser/annotation-service;1"].
  797.                   getService(Ci.nsIAnnotationService);
  798.  
  799.     var callback = {
  800.       _uri: function(aSpec) {
  801.         return Cc["@mozilla.org/network/io-service;1"].
  802.                getService(Ci.nsIIOService).
  803.                newURI(aSpec, null, null);
  804.       },
  805.  
  806.       runBatched: function() {
  807.         var smartBookmarks = [];
  808.         var bookmarksMenuIndex = 0;
  809.         var bookmarksToolbarIndex = 0;
  810.  
  811.         var placesBundle = Cc["@mozilla.org/intl/stringbundle;1"].
  812.                            getService(Ci.nsIStringBundleService).
  813.                            createBundle("chrome://browser/locale/places/places.properties");
  814.  
  815.         // MOST VISITED
  816.         var smart = {queryId: "MostVisited", // don't change this
  817.                      itemId: null,
  818.                      title: placesBundle.GetStringFromName("mostVisitedTitle"),
  819.                      uri: this._uri("place:queryType=" +
  820.                                     Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY +
  821.                                     "&sort=" +
  822.                                     Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
  823.                                     "&maxResults=" + MAX_RESULTS),
  824.                      parent: bmsvc.toolbarFolder,
  825.                      position: bookmarksToolbarIndex++};
  826.         smartBookmarks.push(smart);
  827.  
  828.         // RECENTLY BOOKMARKED
  829.         smart = {queryId: "RecentlyBookmarked", // don't change this
  830.                  itemId: null,
  831.                  title: placesBundle.GetStringFromName("recentlyBookmarkedTitle"),
  832.                  uri: this._uri("place:folder=BOOKMARKS_MENU" +
  833.                                 "&folder=UNFILED_BOOKMARKS" +
  834.                                 "&folder=TOOLBAR" +
  835.                                 "&queryType=" +
  836.                                 Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
  837.                                 "&sort=" +
  838.                                 Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
  839.                                 "&excludeItemIfParentHasAnnotation=livemark%2FfeedURI" +
  840.                                 "&maxResults=" + MAX_RESULTS +
  841.                                 "&excludeQueries=1"),
  842.                  parent: bmsvc.bookmarksMenuFolder,
  843.                  position: bookmarksMenuIndex++};
  844.         smartBookmarks.push(smart);
  845.  
  846.         // RECENT TAGS
  847.         smart = {queryId: "RecentTags", // don't change this
  848.                  itemId: null,
  849.                  title: placesBundle.GetStringFromName("recentTagsTitle"),
  850.                  uri: this._uri("place:"+
  851.                     "type=" +
  852.                     Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
  853.                     "&sort=" +
  854.                     Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_DESCENDING +
  855.                     "&maxResults=" + MAX_RESULTS),
  856.                  parent: bmsvc.bookmarksMenuFolder,
  857.                  position: bookmarksMenuIndex++};
  858.         smartBookmarks.push(smart);
  859.  
  860.         var smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO, {});
  861.         // set current itemId, parent and position if Smart Bookmark exists
  862.         for each(var itemId in smartBookmarkItemIds) {
  863.           var queryId = annosvc.getItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
  864.           for (var i = 0; i < smartBookmarks.length; i++){
  865.             if (smartBookmarks[i].queryId == queryId) {
  866.               smartBookmarks[i].itemId = itemId;
  867.               smartBookmarks[i].parent = bmsvc.getFolderIdForItem(itemId);
  868.               smartBookmarks[i].position = bmsvc.getItemIndex(itemId);
  869.               // remove current item, since it will be replaced
  870.               bmsvc.removeItem(itemId);
  871.               break;
  872.             }
  873.             // We don't remove old Smart Bookmarks because user could still
  874.             // find them useful, or could have personalized them.
  875.             // Instead we remove the Smart Bookmark annotation.
  876.             if (i == smartBookmarks.length - 1)
  877.               annosvc.removeItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
  878.           }
  879.         }
  880.  
  881.         // create smart bookmarks
  882.         for each(var smartBookmark in smartBookmarks) {
  883.           smartBookmark.itemId = bmsvc.insertBookmark(smartBookmark.parent,
  884.                                                       smartBookmark.uri,
  885.                                                       smartBookmark.position,
  886.                                                       smartBookmark.title);
  887.           annosvc.setItemAnnotation(smartBookmark.itemId,
  888.                                     SMART_BOOKMARKS_ANNO, smartBookmark.queryId,
  889.                                     0, annosvc.EXPIRE_NEVER);
  890.         }
  891.         
  892.         // If we are creating all Smart Bookmarks from ground up, add a
  893.         // separator below them in the bookmarks menu.
  894.         if (smartBookmarkItemIds.length == 0)
  895.           bmsvc.insertSeparator(bmsvc.bookmarksMenuFolder, bookmarksMenuIndex);
  896.       }
  897.     };
  898.  
  899.     try {
  900.       bmsvc.runInBatchMode(callback, null);
  901.     }
  902.     catch(ex) {
  903.       Components.utils.reportError(ex);
  904.     }
  905.     finally {
  906.       this._prefs.setIntPref(SMART_BOOKMARKS_PREF, SMART_BOOKMARKS_VERSION);
  907.       this._prefs.QueryInterface(Ci.nsIPrefService).savePrefFile(null);
  908.     }
  909.   },
  910.  
  911. //@line 957 "/build/buildd/firefox-3.5-3.5.5+nobinonly/build-tree/mozilla/browser/components/nsBrowserGlue.js"
  912.  
  913.   // this returns the most recent non-popup browser window
  914.   getMostRecentBrowserWindow : function ()
  915.   {
  916.     var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
  917.              getService(Components.interfaces.nsIWindowMediator);
  918.  
  919. //@line 965 "/build/buildd/firefox-3.5-3.5.5+nobinonly/build-tree/mozilla/browser/components/nsBrowserGlue.js"
  920.     var win = wm.getMostRecentWindow("navigator:browser", true);
  921.  
  922.     // if we're lucky, this isn't a popup, and we can just return this
  923.     if (win && win.document.documentElement.getAttribute("chromehidden")) {
  924.       win = null;
  925.       var windowList = wm.getEnumerator("navigator:browser", true);
  926.       // this is oldest to newest, so this gets a bit ugly
  927.       while (windowList.hasMoreElements()) {
  928.         var nextWin = windowList.getNext();
  929.         if (!nextWin.document.documentElement.getAttribute("chromehidden"))
  930.           win = nextWin;
  931.       }
  932.     }
  933. //@line 991 "/build/buildd/firefox-3.5-3.5.5+nobinonly/build-tree/mozilla/browser/components/nsBrowserGlue.js"
  934.  
  935.     return win;
  936.   },
  937.  
  938.  
  939.   // for XPCOM
  940.   classDescription: "Firefox Browser Glue Service",
  941.   classID:          Components.ID("{eab9012e-5f74-4cbc-b2b5-a590235513cc}"),
  942.   contractID:       "@mozilla.org/browser/browserglue;1",
  943.  
  944.   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
  945.                                          Ci.nsISupportsWeakReference,
  946.                                          Ci.nsIBrowserGlue]),
  947.  
  948.   // redefine the default factory for XPCOMUtils
  949.   _xpcom_factory: BrowserGlueServiceFactory,
  950.  
  951.   // get this contractID registered for certain categories via XPCOMUtils
  952.   _xpcom_categories: [
  953.     // make BrowserGlue a startup observer
  954.     { category: "app-startup", service: true }
  955.   ]
  956. }
  957.  
  958. function GeolocationPrompt() {}
  959.  
  960. GeolocationPrompt.prototype = {
  961.   classDescription: "Geolocation Prompting Component",
  962.   classID:          Components.ID("{C6E8C44D-9F39-4AF7-BCC0-76E38A8310F5}"),
  963.   contractID:       "@mozilla.org/geolocation/prompt;1",
  964.  
  965.   QueryInterface: XPCOMUtils.generateQI([Ci.nsIGeolocationPrompt]),
  966.  
  967.   prompt: function(request) {
  968.     var pm = Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
  969.  
  970.     var result = pm.testExactPermission(request.requestingURI, "geo");
  971.  
  972.     if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
  973.       request.allow();
  974.       return;
  975.     }
  976.     
  977.     if (result == Ci.nsIPermissionManager.DENY_ACTION) {
  978.       request.cancel();
  979.       return;
  980.     }
  981.  
  982.     function setPagePermission(uri, allow) {
  983.       if (allow == true)
  984.         pm.add(uri, "geo", Ci.nsIPermissionManager.ALLOW_ACTION);
  985.       else
  986.         pm.add(uri, "geo", Ci.nsIPermissionManager.DENY_ACTION);
  987.     }
  988.  
  989.     function getChromeWindow(aWindow) {
  990.       var chromeWin = aWindow 
  991.         .QueryInterface(Ci.nsIInterfaceRequestor)
  992.         .getInterface(Ci.nsIWebNavigation)
  993.         .QueryInterface(Ci.nsIDocShellTreeItem)
  994.         .rootTreeItem
  995.         .QueryInterface(Ci.nsIInterfaceRequestor)
  996.         .getInterface(Ci.nsIDOMWindow)
  997.         .QueryInterface(Ci.nsIDOMChromeWindow);
  998.       return chromeWin;
  999.     }
  1000.  
  1001.     var requestingWindow = request.requestingWindow.top;
  1002.     var chromeWindowObject = getChromeWindow(requestingWindow).wrappedJSObject;
  1003.     var tabbrowser = chromeWindowObject.gBrowser;
  1004.     var browser = tabbrowser.getBrowserForDocument(requestingWindow.document);
  1005.     var notificationBox = tabbrowser.getNotificationBox(browser);
  1006.  
  1007.     var notification = notificationBox.getNotificationWithValue("geolocation");
  1008.     if (!notification) {
  1009.       var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
  1010.       var browserBundle = bundleService.createBundle("chrome://browser/locale/browser.properties");
  1011.  
  1012.       var buttons = [{
  1013.               label: browserBundle.GetStringFromName("geolocation.shareLocation"),
  1014.               accessKey: browserBundle.GetStringFromName("geolocation.shareLocation.accesskey"),
  1015.               callback: function(notification) {
  1016.                   var elements = notification.getElementsByClassName("rememberChoice");
  1017.                   if (elements.length && elements[0].checked)
  1018.                       setPagePermission(request.requestingURI, true);
  1019.                   request.allow(); 
  1020.               },
  1021.           },
  1022.           {
  1023.               label: browserBundle.GetStringFromName("geolocation.dontShareLocation"),
  1024.               accessKey: browserBundle.GetStringFromName("geolocation.dontShareLocation.accesskey"),
  1025.               callback: function(notification) {
  1026.                   var elements = notification.getElementsByClassName("rememberChoice");
  1027.                   if (elements.length && elements[0].checked)
  1028.                       setPagePermission(request.requestingURI, false);
  1029.                   request.cancel();
  1030.               },
  1031.           }];
  1032.       
  1033.       var message = browserBundle.formatStringFromName("geolocation.siteWantsToKnow",
  1034.                                                        [request.requestingURI.host], 1);      
  1035.  
  1036.       var newBar = notificationBox.appendNotification(message,
  1037.                                                       "geolocation",
  1038.                                                       "chrome://browser/skin/Geo.png",
  1039.                                                       notificationBox.PRIORITY_INFO_HIGH,
  1040.                                                       buttons);
  1041.  
  1042.       // For whatever reason, if we do this immediately
  1043.       // (eg, without the setTimeout), the "link"
  1044.       // element does not show up in the notification
  1045.       // bar.
  1046.       function geolocation_hacks_to_notification () {
  1047.  
  1048.         // Never show a remember checkbox inside the private browsing mode
  1049.         var inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
  1050.                                 getService(Ci.nsIPrivateBrowsingService).
  1051.                                 privateBrowsingEnabled;
  1052.         if (!inPrivateBrowsing) {
  1053.           var checkbox = newBar.ownerDocument.createElementNS(XULNS, "checkbox");
  1054.           checkbox.className = "rememberChoice";
  1055.           checkbox.setAttribute("label", browserBundle.GetStringFromName("geolocation.remember"));
  1056.           newBar.appendChild(checkbox);
  1057.         }
  1058.  
  1059.         var link = newBar.ownerDocument.createElementNS(XULNS, "label");
  1060.         link.className = "text-link";
  1061.         link.setAttribute("value", browserBundle.GetStringFromName("geolocation.learnMore"));
  1062.  
  1063.         var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter);
  1064.         link.href = formatter.formatURLPref("browser.geolocation.warning.infoURL");
  1065.  
  1066.         var description = newBar.ownerDocument.getAnonymousElementByAttribute(newBar, "anonid", "messageText");
  1067.         description.appendChild(link);
  1068.       };
  1069.  
  1070.       chromeWindowObject.setTimeout(geolocation_hacks_to_notification, 0);
  1071.  
  1072.     }
  1073.   },
  1074. };
  1075.  
  1076.  
  1077. //module initialization
  1078. function NSGetModule(aCompMgr, aFileSpec) {
  1079.   return XPCOMUtils.generateModule([BrowserGlue, GeolocationPrompt]);
  1080. }
  1081.